// LangUtils.cpp

#include "StdAfx.h"

#include "LangUtils.h"
#include "Common/String/StringConvert.h"
#include "Common/String/StringToInt.h"
#include "Common/FileSystem/FileFind.h"
#include "Common/Registry/RegistryUtils.h"
#include "Common/App/ProgramLocation.h"

#include "Common/System/Threading/Utility.h"

using namespace Common;
using namespace System;

static Lang::CLang g_Lang;
CString g_LangID;

namespace Common
{
namespace Lang
{

void ReloadLang()
{
	Registry::ReadRegLang(g_LangID);
  g_Lang.Clear();
  if (!g_LangID.IsEmpty() && g_LangID != _T("-"))
  {
    CString langPath = g_LangID;
    if (langPath.Find(CHAR_PATH_SEPARATOR) < 0)
    {
      if (langPath.Find(_T('.')) < 0)
        langPath += _T(".txt");
      CString folderPath;
      if (App::GetProgramFolderPath(folderPath))
        langPath = folderPath + CString(_T("Lang") STRING_PATH_SEPARATOR) + langPath;
    }
    g_Lang.Open(langPath);
  }
}

//TODO: check if those two variables are needed or at least locking
static bool g_Loaded = false;
static CComAutoCriticalSection g_CriticalSection;

void LoadLangOneTime()
{
	Threading::CComScopeAutoLock lock(g_CriticalSection);
  if (g_Loaded)
    return;
  g_Loaded = true;
  ReloadLang();
}

void LangSetDlgItemsText(HWND dialogWindow, CIDLangPair *idLangPairs, int numItems)
{
  for (int i = 0; i < numItems; i++)
  {
    const CIDLangPair &idLangPair = idLangPairs[i];
    CString message;
    if (g_Lang.GetMessage(idLangPair.LangID, message))
    {
      CWindow window(GetDlgItem(dialogWindow, idLangPair.ControlID));
      window.SetWindowText(message);
    }
  }
}

void LangSetWindowText(HWND window, UINT32 langID)
{
  CString message;
  if (g_Lang.GetMessage(langID, message))
    SetWindowText(window, message);
}

CString LangString(UINT32 langID)
{
  CString message;
  if (g_Lang.GetMessage(langID, message))
    return message;
  return CString();
}

CString LangString(UINT resourceID, UINT32 langID)
{
  CString message;
  if (!g_Lang.GetMessage(langID, message))    
	message = Common::String::LoadString(resourceID);
  return message;
}

void LoadLangs(std::vector<CLangEx> &langs)
{
  langs.clear();
  CString folderPath;
  if (!App::GetProgramFolderPath(folderPath))
    return;
  folderPath += _T("Lang") STRING_PATH_SEPARATOR;
  FileSystem::Find::CEnumerator enumerator(folderPath + _T("*.txt"));
  FileSystem::File::CFileInfo fileInfo;
  while (enumerator.Next(&fileInfo))
  {
    if (fileInfo.IsDir())
      continue;
    CLangEx lang;
    CString filePath = folderPath + fileInfo.Name;
    const int kExtSize = 4;
    const CString ext = fileInfo.Name.Right(kExtSize);
    if (ext.CompareNoCase(_T(".txt")) != 0)
      continue;
    lang.ShortName = fileInfo.Name.Left(fileInfo.Name.GetLength() - kExtSize);
    if (lang.Lang.Open(filePath))
		langs.push_back(lang);
  }
}

bool SplidID(const CString &id, WORD &primID, WORD &subID)
{
  primID = 0;
  subID = 0;
  LPCTSTR start = id;
  LPCTSTR end;
  UINT64 value = String::ConvertStringToUInt64(start, &end);
  if (start == end)
    return false;
  primID = (WORD)value;
  if (*end == 0)
    return true;
  if (*end != _T('-'))
    return false;
  start = end + 1;
  value = String::ConvertStringToUInt64(start, &end);
  if (start == end)
    return false;
  subID = (WORD)value;
  return (*end == 0);
}

typedef LANGID (WINAPI *GetUserDefaultUILanguageP)();

void FindMatchLang(CString &shortName)
{
  shortName.Empty();

  LANGID SystemDefaultLangID = GetSystemDefaultLangID(); // Lang for non-Unicode in XP64
  LANGID UserDefaultLangID = GetUserDefaultLangID(); // Standarts and formats in XP64

  if (SystemDefaultLangID != UserDefaultLangID)
    return;
  LANGID langID = UserDefaultLangID;
  /*
  LANGID SystemDefaultUILanguage; // english  in XP64
  LANGID UserDefaultUILanguage; // english  in XP64

  GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress(
      GetModuleHandle("kernel32"), "GetUserDefaultUILanguage");
  if (fn != NULL)
    UserDefaultUILanguage = fn();
  fn = (GetUserDefaultUILanguageP)GetProcAddress(
      GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage");
  if (fn != NULL)
    SystemDefaultUILanguage = fn();
  */

  WORD primLang = (WORD)(PRIMARYLANGID(langID));
  WORD subLang = (WORD)(SUBLANGID(langID));
  std::vector<CLangEx> langs;
  LoadLangs(langs);
  for (size_t i = 0; i < langs.size(); i++)
  {
    const CLangEx &lang = langs[i];
    CString id;
    if (lang.Lang.GetMessage(0x00000002, id))
    {
      WORD primID;
      WORD subID;
      if (SplidID(id, primID, subID))
        if (primID == primLang)
        {
          if (subID == 0)
            shortName = lang.ShortName;
          if (subLang == subID)
          {
            shortName = lang.ShortName;
            return;
          }
        }
    }
  }
}

void ReloadLangSmart()
{
    Registry::ReadRegLang(g_LangID);
    if (g_LangID.IsEmpty())
    {
      CString shortName;
      FindMatchLang(shortName);
      if (shortName.IsEmpty())
        shortName = _T("-");
      Registry::SaveRegLang(shortName);
    }
  
  ReloadLang();
}

}
}